using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data;
using System.Windows.Forms;
using System.Xml.Schema;
using System.IO;
using System.Drawing;
using OpenComposite.Base;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.RepositoryUIs;
using OpenComposite.Base.Collections;

namespace OpenComposite.EII.Repository
{
	[RepositoryItem(ItemType.HumanActivity, "human_activities", "hact_id")]
	public class HumanActivity : RepositoryItemBaseEx
	{
		#region Initialization
		/// <summary>
		/// Initializes a new instance of the <see cref="HumanActivity"/> class.
		/// </summary>
		public HumanActivity()
			: base("hact_id", "hact_nm", "hact_desc", "hact_ntext", Resources.sNewHumanActivity)
		{
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="HumanActivity"/> class.
		/// </summary>
		/// <param name="bCreateNew">if set to <c>true</c> [b create new].</param>
		public HumanActivity(bool bCreateNew)
			: this()
		{
			if ( bCreateNew )
				this.CreateNew();
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="HumanActivity"/> class.
		/// </summary>
		/// <param name="id">The id.</param>
		public HumanActivity(int id)
			: this()
		{
			this.Load(id);
		}
		#endregion

		#region Properties

		/// <summary>
		/// Gets or sets the form schema.
		/// </summary>
		/// <value>The form schema.</value>
		public XmlSchema FormSchema
		{
			get { return getSchema("hact_schema"); }
			set { setSchema("FormSchema", "hact_schema", value, EncryptCompressMode.None); }
		}
		/// <summary>
		/// Gets or sets the name of the form schema.
		/// </summary>
		/// <value>The name of the form schema.</value>
		public string FormSchemaName
		{
			get { return getString("hact_schema_nm", ""); }
			set { setValue("FormSchemaName", "hact_schema_nm", value); }
		}
		/// <summary>
		/// Gets or sets the form DLL.
		/// </summary>
		/// <value>The form DLL.</value>
		public byte[] FormDLL
		{
			get { return getBytes("hact_form_dll"); }
			set { setValue("FormDLL", "hact_form_dll", value); }
		}
		/// <summary>
		/// Gets or sets the name of the form assembly.
		/// </summary>
		/// <value>The name of the form assembly.</value>
		public string FormAssemblyName
		{
			get { return getString("hact_form_asm_nm", ""); }
			set { setValue("FormAssemblyName", "hact_form_asm_nm", value); }
		}
		/// <summary>
		/// Gets or sets the assembly form names.
		/// </summary>
		/// <value>The assembly form names.</value>
		public string[] AssemblyFormNames
		{
			get
			{
				string s = getString("hact_assembly_forms", null);
				if ( !string.IsNullOrEmpty(s) ) {
					return s.Split(';');
				} else {
					return new string[0];
				}
			}
			set
			{
				if ( value != null ) {
					setValue("AssemblyFormNames", "hact_assembly_forms", string.Join(";", value));
				} else {
					setValue("AssemblyFormNames", "hact_assembly_forms", null);
				}
			}
		}
		/// <summary>
		/// Gets or sets the name of the form.
		/// </summary>
		/// <value>The name of the form.</value>
		public string FormName
		{
			get { return getString("hact_form_nm", ""); }
			set { setValue("FormName", "hact_form_nm", value); }
		}
		/// <summary>
		/// Gets or sets the URL.
		/// </summary>
		/// <value>The URL.</value>
		public Uri Url
		{
			get
			{
				string url = getString("hact_url", null);
				if ( string.IsNullOrEmpty(url) ) {
					Uri uri = CreateUri(Environment.MachineName);
					this.Url = uri;
					return uri;
				} else
					return new Uri(url);
			}
			set { setValue("Url", "hact_url", value == null ? null : value.ToString()); }
		}

		/// <summary>
		/// Gets or sets the URL template.
		/// </summary>
		/// <value>The URL template.</value>
		public string UrlTemplate
		{
			get { return getString("hact_url_template", null); }
			set { setValue("UrlTemplate", "hact_url_template", value); }
		}

		/// <summary>
		/// Gets the image key.
		/// </summary>
		/// <value>The image key.</value>
		public override string ImageKey
		{
			get { return "ha_component"; }
		}
		/// <summary>
		/// Gets the selected image key.
		/// </summary>
		/// <value>The selected image key.</value>
		public override string SelectedImageKey
		{
			get { return "ha_component"; }
		}
		/// <summary>
		/// Gets the image.
		/// </summary>
		/// <value>The image.</value>
		public override Image Image
		{
			get { return Resources.png_user; }
		}
		/// <summary>
		/// Gets the selected image.
		/// </summary>
		/// <value>The selected image.</value>
		public override Image SelectedImage
		{
			get { return this.Image; }
		}

		/// <summary>
		/// Gets the type of the repository item.
		/// </summary>
		/// <value>The type of the repository item.</value>
		public override ItemType RepositoryItemType
		{
			get { return ItemType.HumanActivity; }
		}
		/// <summary>
		/// Gets the name of the repository item type.
		/// </summary>
		/// <value>The name of the repository item type.</value>
		public override string RepositoryItemTypeName
		{
			get { return Resources.sHumanActivity; }
		}
		/// <summary>
		/// Gets the repository item type description.
		/// </summary>
		/// <value>The repository item type description.</value>
		public override string RepositoryItemTypeDescription
		{
			get { return ""; }
		}

		/// <summary>
		/// Gets the name of the table.
		/// </summary>
		/// <value>The name of the table.</value>
		public override string TableName
		{
			get { return "human_activities"; }
		}
		private static List<ItemType> _LISTALLOWED = new List<ItemType>();
		/// <summary>
		/// Gets the allowed child types.
		/// </summary>
		/// <value>The allowed child types.</value>
		public override List<ItemType> AllowedChildTypes
		{
			get { return _LISTALLOWED; }
		}

		/// <summary>
		/// Gets the display text.
		/// </summary>
		/// <value>The display text.</value>
		public override string Display
		{
			get
			{
				return this.Name;
			}
		}

		/// <summary>
		/// Gets or sets the web service ID.
		/// </summary>
		/// <value>The web service ID.</value>
		public int WebServiceID
		{
			get { return getInt("hact_websvc_id", -1); }
			set { setValue("WebServiceID", "hact_websvc_id", value); }
		}
		/// <summary>
		/// Gets or sets the web service.
		/// </summary>
		/// <value>The web service.</value>
		public WebService WebService
		{
			get
			{
				if ( this.WebServiceID > 0 )
					return this.RepositoryService.GetItem(ItemType.WebService, this.WebServiceID, false) as WebService;
				else
					return null;
			}
			set { this.WebServiceID = ( value == null ? -1 : value.ID ); }
		}

		#endregion

		#region Methods

		/// <summary>
		/// Shows the new item form.
		/// </summary>
		/// <param name="idRepository">The repository ID.</param>
		/// <param name="bAllowContinue">if set to <c>true</c> to allow save and continue.</param>
		/// <param name="parentItem">The parent item.</param>
		/// <param name="idDomain">The domain ID.</param>
		/// <param name="parentItemNew">The new parent item.</param>
		/// <returns></returns>
		public override DialogResult ShowNewItemForm(int idRepository, bool bAllowContinue,
			IRepositoryItem parentItem, ref int idDomain, out IRepositoryItem parentItemNew)
		{
			return base.ShowNewItemForm(idRepository, bAllowContinue, parentItem, ref idDomain, out parentItemNew);
		}
		/// <summary>
		/// Gets the icon.
		/// </summary>
		/// <returns></returns>
		public override Icon GetIcon()
		{
			return Icon.FromHandle(Resources.png_user.GetHicon());
		}
		/// <summary>
		/// Returns a <see cref="System.String"/> that represents this instance.
		/// </summary>
		/// <returns>
		/// A <see cref="System.String"/> that represents this instance.
		/// </returns>
		public override string ToString()
		{
			return this.Name;
		}

		/// <summary>
		/// Saves this instance.
		/// </summary>
		/// <returns></returns>
		public override bool Save()
		{
			WebService ws = null;
			if ( this.RepositoryService != null ) {
				ws = this.WebService;
				if ( ws == null ) {
					IRepositoryItem parentItem = null;
					ws = this.RepositoryService.GetNewItem(ItemType.WebService, false, ref parentItem) as WebService;
					this.WebService = ws;
				}
				// update urltemplate
				string template = "{0}://{1}:{2}/{3}/{4}/{5}";
				string orgnm = RepositoryService.GetIdentifier(Global.CurrentUser.OrganizationName);
				Domain d = this.RepositoryService.GetItem<Domain>(this.DomainId);
				string domainnm = "default";
				if ( d != null ) {
					domainnm = RepositoryService.GetIdentifier(d.Name);
				}
				this.UrlTemplate = string.Format(template,
												 "<TYPE>",
												 "<SERVER>",
												 "<PORT>",
												 orgnm,
												 domainnm,
												 this.Name);
				// create webservice
				ws.BeginEdit();
				try {
					ws.Name = this.Name;
					if ( this.Url != null )
						ws.Uri = this.Url.ToString();
					ws.EndEdit(true);
				} catch {
					ws.CancelEdit();
					throw;
				}
				this.WebService = ws;
			}
			bool ok = base.Save();
			if ( !ok || ws == null || Global.Status.CurrentRepositoryId <= 0 )
				return ok;

			// create webmethod
			WebMethod wmethHA;
			BindingListEx<WebMethod> wmeths = ws.GetWebMethods();
			if ( wmeths == null || wmeths.Count == 0 ) {
				IRepositoryItem parentItem = ws;
				wmethHA = this.RepositoryService.GetNewItem(ItemType.WebMethod, false, ref parentItem) as WebMethod;
			} else {
				wmethHA = wmeths[0];
			}
			wmethHA.BeginEdit();
			try {
				string[] fsnSplit = this.FormSchemaName.Split('.');
				string fsname = fsnSplit[fsnSplit.Length - 1]; //
				wmethHA.Name = "DoHumanActivity";
				wmethHA.InputAction = "http://www.OpenComposite.com/HumanActivity/IHumanActivityService/HumanActivityStart";
				wmethHA.InputSchema = this.FormSchema;
				wmethHA.InputTypeName = fsname; //this.FormSchemaName;
				wmethHA.InputVariableName = fsname; //this.FormSchemaName;
				wmethHA.OutputAction = "http://www.OpenComposite.com/HumanActivity/IHumanActivityServiceCallback/HumanActivityCompleted";
				wmethHA.OutputSchema = this.FormSchema;
				wmethHA.OutputTypeName = fsname; //this.FormSchemaName;
				wmethHA.OutputVariableName = fsname; //this.FormSchemaName;
				wmethHA.PortType = "IHumanActivityService";
				wmethHA.Action = "http://www.OpenComposite.com/HumanActivity/IHumanActivityService/HumanActivityStart";

				wmethHA.EndEdit(true);
			} catch {
				wmethHA.CancelEdit();
				throw;
			}
			Global.Data.AddRepositoryHierarchy(ws, wmethHA, Global.Status.CurrentRepositoryId);

			return ok;
		}

		/// <summary>
		/// Creates the URI.
		/// </summary>
		/// <param name="hostName">Name of the host.</param>
		/// <returns></returns>
		public Uri CreateUri(string hostName)
		{
			string template = "{0}://{1}:{2}/{3}/{4}/{5}";
			string orgnm = RepositoryService.GetIdentifier(Global.CurrentUser.OrganizationName);
			Domain d = this.RepositoryService.GetItem<Domain>(this.DomainId);
			string domainnm = "default";
			if ( d != null ) {
				domainnm = RepositoryService.GetIdentifier(d.Name);
			}
			this.UrlTemplate = string.Format(template,
											 "<TYPE>",
											 "<SERVER>",
											 "<PORT>",
											 orgnm,
											 domainnm,
											 this.Name);
			Uri uri = new Uri(string.Format(template,
											"net.tcp",
											hostName,
											Global.Data.GetHumanActivityPort(),
											orgnm,
											domainnm,
											this.Name));
			return uri;
		}

		/// <summary>
		/// Copies this instance.
		/// </summary>
		/// <param name="deep"><c>true</c> to recursively copy the item and all subitems;
		/// <c>false</c> to copy only the item itself.</param>
		/// <returns>The copied item.</returns>
		public override IRepositoryItem Copy(bool deep)
		{
			HumanActivity copy = new HumanActivity(true);
			copy.InitializeServiceProvider(this);
			this.CopyDataRowToTarget(copy);
			return copy;
		}

		#endregion

		#region Constants
		internal const string ColumnID = "hact_id";
		internal const string ColumnName = "hact_nm";
		internal const string ColumnDescription = "hact_desc";
		internal const string ColumnNText = "hact_ntext";
		#endregion
	}
}